
Tapestry.Validator.hvCreditCardNumber = function(field, message) {
    field.addValidator(function(value) {
    	if (! Tapestry.Validator.hvLuhnValidator(value, 2)) {
    		throw message;
    	}
    });
};

Tapestry.Validator.hvDigits = function(field, message, params) {
	params = params.evalJSON();
    field.addValidator(function(value) {
    	
    	var stringValue = value+"";
    	
		var pos = stringValue.indexOf( '.' );

		var left = ( pos == -1 ) ?
				stringValue.length :
				pos;
		var right = ( pos == -1 ) ?
				0 :
				stringValue.length - pos - 1;

		if ( left == 1 && stringValue.charAt( 0 ) == '0' ) {
			left--;
		}
    	
		var valid =  !( left > params.integerDigits || right > params.fractionalDigits );
    	
    	if (!valid) {
    		throw message;
    	}
    });
};

Tapestry.Validator.hvEAN = function(field, message) {
    field.addValidator(function(value) {
    	
    	var str =  value + "";

    	var zeroCode = "0".charCodeAt(0);
    	ints = [];
    	for (i=0;i<str.length;i++) {
    		var c = str.charAt(i);
    		if ( Tapestry.Validator.hvIsDigit(c) ) { 
    			ints[ints.length] = ( str.charCodeAt(i) -  zeroCode);
    		}
    	}
    	var length = ints.length;
    	var sum = 0;
    	even = false;
    	for ( index = length - 1 ; index >= 0 ; index-- ) {
    		var digit = ints[index];
    		if  (even) {
    			digit *= 3;
    		}
    		sum+= digit;
    		even = !even;
    	}
    	
    	if ( sum % 10 != 0) {
    		throw message;
    	}
    });
};

Tapestry.Validator.hvEmail = function(field, message) {
    field.addValidator(function(value) {
    	if (!Tapestry.Validator.isRFC822ValidEmail(value)) {
    		throw message;
    	}
    });
};


Tapestry.Validator.hvLength = function(field, message, params) {
	params = params.evalJSON();
    field.addValidator(function(value) {
		value = value + "";
		if (!value.empty()) {
        	var length = value.length;
        	var valid = length >= params.min && length <= params.max;
        	if (!valid) {
        		throw message;
        	}
		}
    });
};

Tapestry.Validator.hvPattern = function(field, message, params) {
	params = params.evalJSON();
	var regexp = new RegExp(params.regex, params.flags);
    field.addValidator(function(value) {
        if (  value != value.match(regexp) ) throw message;
    });
};

Tapestry.Validator.hvRange = function(field, message, params) {
	params = params.evalJSON();
	var regexp = new RegExp(params.regex, params.flags);
    field.addValidator(function(value) {
    	var valid = value >= params.min && value <= params.max;
        if (  !valid ) throw message;
    });
};




Tapestry.Validator.isRFC822ValidEmail = function(sEmail) {
	
	var sQtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]';
	var sDtext = '[^\\x0d\\x5b-\\x5d\\x80-\\xff]';
	var sAtom = '[^\\x00-\\x20\\x22\\x28\\x29\\x2c\\x2e\\x3a-\\x3c\\x3e\\x40\\x5b-\\x5d\\x7f-\\xff]+';
	var sQuotedPair = '\\x5c[\\x00-\\x7f]';
	var sDomainLiteral = '\\x5b(' + sDtext + '|' + sQuotedPair + ')*\\x5d';
	var sQuotedString = '\\x22(' + sQtext + '|' + sQuotedPair + ')*\\x22';
	var sDomain_ref = sAtom;
	var sSubDomain = '(' + sDomain_ref + '|' + sDomainLiteral + ')';
	var sWord = '(' + sAtom + '|' + sQuotedString + ')';
	var sDomain = sSubDomain + '(\\x2e' + sSubDomain + ')*';
	var sLocalPart = sWord + '(\\x2e' + sWord + ')*';
	var sAddrSpec = sLocalPart + '\\x40' + sDomain; // complete RFC822 email address spec
	var sValidEmail = '^' + sAddrSpec + '$'; // as whole string
	  
	var reValidEmail = new RegExp(sValidEmail);
	  
	if (reValidEmail.test(sEmail)) {
	  return true;
	}
	  
	return false;
};


Tapestry.Validator.hvDigitsChars = "0123456789";

Tapestry.Validator.hvIsDigit = function(c) {
	return Tapestry.Validator.hvDigitsChars.indexOf(c) > -1;
};


Tapestry.Validator.hvLuhnValidator = function(value, multiplicator) {
	
	var creditCard = value+"";

	var zeroCode = "0".charCodeAt(0);
	ints = [];
	for (i=0;i<creditCard.length;i++) {
		var c = creditCard.charAt(i);
		if ( Tapestry.Validator.hvIsDigit(c)) {
			ints[ints.length] = ( creditCard.charCodeAt(i) -  zeroCode);
		}
	}
	var length = ints.length;
	var sum = 0;
	even = false;
	for ( index = length - 1 ; index >= 0 ; index-- ) {
		var digit = ints[index];
		if  (even) {
			digit *= multiplicator;
		}
		if (digit > 9) {
			digit = digit / 10 + digit % 10;
		}
		sum+= digit;
		even = !even;
	}
	return  sum % 10 == 0;
};

